/*
 * Niiuzu
 * Copyright (C) 2011  Thierry Nowak
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.niiuzu.client.screen.feed.channel.factory;

import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.HasValue;
import com.google.inject.Inject;
import com.mvp4g.client.annotation.Presenter;
import com.mvp4g.client.presenter.LazyPresenter;
import com.niiuzu.client.eventbus.FeedEventBus;
import com.niiuzu.client.i18n.FeedChannelMessages;
import com.niiuzu.client.util.ClientContextFactory;
import com.niiuzu.client.util.LoadingTicket;
import com.niiuzu.client.util.SessionClient;
import com.niiuzu.client.util.callback.AbstractCallback;
import com.niiuzu.client.util.widget.HasSelectedValue;
import com.niiuzu.shared.model.FeedChannel;
import com.niiuzu.shared.model.FeedChannelGroup;
import com.niiuzu.shared.rpc.FeedServiceAsync;

/**
 * Presenter dédié à la création de nouveaux flux.
 */
@Presenter(view = ChannelFactoryViewImpl.class)
public class ChannelFactoryPresenter extends
		LazyPresenter<ChannelFactoryView, FeedEventBus> {

	@Inject
	private FeedServiceAsync feedService;

	private ClickHandler closeClickHandler;
	private ClickHandler validateClickHandler;

	private FeedChannelMessages feedChannelMessages = GWT
			.create(FeedChannelMessages.class);

	@Override
	public void bindView() {
		super.bindView();

		closeClickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				view.hidePopup();
			}
		};
		view.getCloseButtonHasClickHandlers()
				.addClickHandler(closeClickHandler);
		view.getCancelHasClickHandlers().addClickHandler(closeClickHandler);

		validateClickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				validateChannelCreation();
			}
		};
		view.getValidateHasClickHandlers()
				.addClickHandler(validateClickHandler);
	}

	/**
	 * Lance la validation de la création d'un nouveau flux.
	 */
	private void validateChannelCreation() {

		HasValue<String> urlField = view.getUrlHasValue();
		HasValue<String> nameField = view.getNameHasValue();
		HasSelectedValue<String> groupField = view.getGroupHasSelectedValue();

		String errorMessage = null;
		if (urlField.getValue().isEmpty()) {
			errorMessage = feedChannelMessages.errorChannelUrlMissing();
		} else if (nameField.getValue().isEmpty()) {
			errorMessage = feedChannelMessages.errorChannelNameMissing();
		} else if (groupField.getSelectedValue() == null) {
			errorMessage = feedChannelMessages.errorChannelGroupMissing();
		}

		// Affichage d'un message d'erreur
		if (errorMessage != null) {
			eventBus.businessErrorOccurred(errorMessage);
		}
		// Lancement de la création du flux à partir des informations saisis
		else {
			SessionClient sessionClient = SessionClient.getInstance();

			String channelUrl = urlField.getValue();
			String channelName = nameField.getValue();

			String channelGroupUid = groupField.getSelectedValue();

			Map<String, FeedChannelGroup> channelGroupMap;
			channelGroupMap = sessionClient.getChannelGroupMap();
			FeedChannelGroup channelGroup = channelGroupMap
					.get(channelGroupUid);

			final LoadingTicket ticket = LoadingTicket.Factory.createTicket(
					getClass(), feedChannelMessages.loadingCreateChannel());

			eventBus.loadingStarted(ticket);

			feedService.createChannel(channelUrl, channelName, channelGroup,
					ClientContextFactory.get(),
					new AbstractCallback<FeedChannel>(eventBus, ticket) {
						@Override
						public void onSuccess(FeedChannel result) {
							receiveCreatedChannel(result, ticket);
						}
					});
		}
	}

	/**
	 * Réception d'une demande de création d'un nouveau flux.
	 * 
	 * @see FeedEventBus#newChannelAsked()
	 */
	public void onNewChannelAsked() {

		view.getUrlHasValue().setValue("");
		view.getNameHasValue().setValue("");
		view.getGroupHasSelectedValue().clear();

		SessionClient sessionClient = SessionClient.getInstance();
		Collection<FeedChannelGroup> channelGroupCollection;
		channelGroupCollection = sessionClient.getChannelGroupMap().values();

		FeedChannelGroup[] channelGroupArray;
		channelGroupArray = new FeedChannelGroup[channelGroupCollection.size()];
		channelGroupArray = channelGroupCollection.toArray(channelGroupArray);

		// Tri des thèmes récupérés
		Arrays.sort(channelGroupArray, new Comparator<FeedChannelGroup>() {
			@Override
			public int compare(FeedChannelGroup o1, FeedChannelGroup o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});

		// Remplissage de la liste des thèmes à chaque nouvel affichage
		view.getGroupHasSelectedValue().addValue("", null);
		for (FeedChannelGroup channelGroup : channelGroupArray) {
			view.getGroupHasSelectedValue().addValue(channelGroup.getName(),
					channelGroup.getUid());
		}

		view.showPopup();
	}

	/**
	 * Comportement déclenché à la demande de fermeture de la popup.
	 */
	public ClickHandler getCloseClickHandler() {
		return closeClickHandler;
	}

	/**
	 * Comportement déclenché suite au clic sur le bouton de validation.
	 */
	public ClickHandler getValidateClickHandler() {
		return validateClickHandler;
	}

	/**
	 * Réception d'un flux venant d'être créé.
	 * 
	 * @param feedChannel
	 *            flux créé.
	 * @param ticket
	 *            correspondant a l'appel asynchrone de la création.
	 */
	void receiveCreatedChannel(FeedChannel feedChannel, LoadingTicket ticket) {

		SessionClient.getInstance().addChannel(feedChannel);

		view.hidePopup();
		eventBus.loadingFinished(ticket);

		eventBus.channelCreated();
	}

	/* ********************************************************************** */
	/* ********************************************************************** */
	/* ********************************************************************** */

	/**
	 * JUnit - Définit un mock pour {@link FeedChannelMessages}.
	 */
	void setMockedFeedChannelMessages(
			FeedChannelMessages mockedFeedChannelMessages) {
		this.feedChannelMessages = mockedFeedChannelMessages;
	}

	/**
	 * JUnit - Définit un mock pour {@link FeedServiceAsync}.
	 */
	void setMockedFeedServiceAsync(FeedServiceAsync mockedFeedService) {
		this.feedService = mockedFeedService;
	}
}
